// Copyright IBM Corp. and LoopBack contributors 2020. All Rights Reserved.
// Node module: @loopback/example-todo-jwt
// This file is licensed under the MIT License.
// License text available at https://opensource.org/licenses/MIT

import {authenticate, TokenService} from '@loopback/authentication';
import {
  Credentials,
  RefreshTokenService,
  RefreshTokenServiceBindings,
  TokenObject,
  TokenServiceBindings
} from '@loopback/authentication-jwt';
import {inject} from '@loopback/core';
import {repository} from '@loopback/repository';
import {
  get,
  param,
  post,
  requestBody
} from '@loopback/rest';
import {securityId} from '@loopback/security';
import {RefreshGrantRequestBody} from '../class/user.class';
import {RefreshGrant} from '../interfaces';
import {MyUserRepository} from '../repositories';


/**
 * 获取登录token、刷新token的信息
 *
 * @export
 * @class UserController
 */
export class UserController {
  constructor(
    @inject(TokenServiceBindings.TOKEN_SERVICE)
    public jwtService: TokenService,
    // @inject(UserServiceBindings.USER_SERVICE)
    // public userService: MyUserService,
    // @inject(SecurityBindings.USER, {optional: true})
    // public user: UserProfile,
    // @repository(UserRepository) protected userRepository: UserRepository,
    @inject(RefreshTokenServiceBindings.REFRESH_TOKEN_SERVICE)
    public refreshService: RefreshTokenService,
    @repository(MyUserRepository) public myUserRepository: MyUserRepository,
  ) { }

  @post('/users/login', {
    responses: {
      '200': {
        description: '登录成功后获取的 Token',
        content: {
          'application/json': {
            schema: {
              type: 'object',
              properties: {
                token: {
                  type: 'string',
                },
              },
            },
          },
        },
      },
    },
  })
  async login(
    @requestBody({
      description: 'The input of login function 输入邮箱和密码',
      required: true,
      content: {
        'application/json': {
          schema: {
            type: 'object',
            required: ['email', 'password'],
            example: {
              "email": "userEmail@xx.com",
              "password": "123456789",
            },
            properties: {
              email: {
                type: 'string',
                format: 'email',
              },
              password: {
                type: 'string',
                minLength: 8,
              },
            },
          }
        },
      },
    }
    ) credentials: Credentials,
  ): Promise<{token: string}> {
    // console.log(credentials);
    const user = await this.myUserRepository.findOne({
      where: {
        email: credentials.email,
        password: credentials.password
      }
    })
    console.log(user);
    if (!user) throw new Error('error')

    // create a JSON Web Token based on the user profile
    const token = await this.jwtService.generateToken({
      name: user!.name,
      id: user!.id,
      email: user!.email,
      [securityId]: user!.uid
    });
    console.log(token);

    return {token};
  }

  @authenticate('jwt')
  @get('/whoAmI', {
    responses: {
      '200': {
        description: 'Return current user',
        content: {
          'application/json': {
            schema: {
              type: 'string',
            },
          },
        },
      },
    },
  })
  async whoAmI(
    @param.query.string('email', {required: true, example: 'userEmail@xx.com'})
    email: string,
  ): Promise<string> {
    const data = await this.myUserRepository.findOne({
      where: {
        email
      }
    })
    if (!data) throw new Error('error')
    return data!.name as string
  }

  /**
    * 刷新
    * A login function that returns refresh token and access token.
    * @param credentials User email and password
  */
  @post('/users/refresh-login', {
    responses: {
      '200': {
        description: 'Token',
        content: {
          'application/json': {
            schema: {
              type: 'object',
              properties: {
                accessToken: {
                  type: 'string',
                },
                refreshToken: {
                  type: 'string',
                },
              },
            },
          },
        },
      },
    },
  })
  async refreshLogin(
    @requestBody({
      description: 'The input of login function',
      required: true,
      content: {
        'application/json': {
          schema: {
            type: 'object',
            required: ['email', 'password'],
            example: {
              "email": "userEmail@xx.com",
              "password": "123456789",
            },
            properties: {
              email: {
                type: 'string',
                format: 'email',
              },
              password: {
                type: 'string',
                minLength: 8,
              },
            },
          }
        },
      },
    }) credentials: Credentials,
  ): Promise<TokenObject> {
    const user = await this.myUserRepository.findOne({
      where: {
        email: credentials.email,
        password: credentials.password
      }
    })
    // console.log(user);
    if (!user) throw new Error('error')
    const userProfile = {
      name: user!.name,
      id: user!.id,
      email: user!.email,
      [securityId]: user!.uid
    }
    const accessToken = await this.jwtService.generateToken(userProfile);
    const tokens = await this.refreshService.generateToken(
      userProfile,
      accessToken,
    );
    return tokens;
  }

  @post('/refresh', {
    responses: {
      '200': {
        description: 'Token',
        content: {
          'application/json': {
            schema: {
              type: 'object',
              properties: {
                accessToken: {
                  type: 'object',
                },
              },
            },
          },
        },
      },
    },
  })
  async refresh(
    @requestBody(RefreshGrantRequestBody) refreshGrant: RefreshGrant,
  ): Promise<TokenObject> {
    return this.refreshService.refreshToken(refreshGrant.refreshToken);
  }
}
